package com.basis.utils;

import com.mes.data.EmesCodeRule;
import com.mes.data.EmesCodeRuleCombination;
import org.hibernate.Query;
import org.openbravo.base.exception.OBException;
import org.openbravo.dal.core.SessionHandler;
import org.openbravo.dal.service.OBDal;
import org.openbravo.database.SessionInfo;
import org.openbravo.model.ad.access.User;
import org.openbravo.model.ad.datamodel.Column;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("unchecked")
public class CodeGenerateRuleUtil {
	private static final SimpleDateFormat yyyyMM = new SimpleDateFormat("yyMM");
	private static final SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyMMdd");

	/**
	 * 根据表名获取表中所有字段编码规则值
	 */
	public static synchronized Map<String, String> getCodeByTableName(String tableName) {
		Map<String, String> map = new HashMap<String, String>();
		String hql = "select cg from Emes_Code_Rule cg where cg.emesCodeRuleObject.table.name = '" + tableName + "'";
		Query query = OBDal.getInstance().getSession().createQuery(hql);
		List<EmesCodeRule> list = query.list();
		Column column = null;
		for (EmesCodeRule rule : list) {
			// 自动生成
			if (rule.isGenerate()) {
				column = rule.getEmesCodeRuleObject().getColumn();
				map.put(column.getDBColumnName(), createCode(rule));
			}
		}
		return map;
	}
	/**
	 * 根据表ID获取表中所有字段编码规则值
	 */
	public static synchronized Map<String, String> autoGenerateCode(String tableId) {
		List<EmesCodeRule> list = getCodeRuleList(tableId);
		Map<String, String> map = new HashMap<String, String>();
		Column column = null;
		for (EmesCodeRule rule : list) {
			// 自动生成
			if (rule.isGenerate()) {
				column = rule.getEmesCodeRuleObject().getColumn();
				map.put(column.getDBColumnName(), createCode(rule));
			}
		}
		return map;
	}
	/**
	 * 根据表ID，字段名获取编码规则结果
	 */
	public static synchronized String getCode(String tableId, String fieldName) {
		List<EmesCodeRule> list = getCodeRuleList(tableId);
		Column column = null;
		for (EmesCodeRule rule : list) {
			// 自动生成
			column = rule.getEmesCodeRuleObject().getColumn();
			if (column != null && column.getDBColumnName().equalsIgnoreCase(fieldName)) {
				return createCode(rule);
			}
		}
		throw new OBException("字段" + fieldName + "未设置编码规则");
	}
	
	private static List<EmesCodeRule> getCodeRuleList(String tableId) {
		String hql = "select ad_table_id from ad_table where upper(tablename) = ?";
		Object adTableId = OBDal.getInstance().getSession().createSQLQuery(hql).setString(0, tableId.toUpperCase()).uniqueResult();
		if (adTableId == null) {
			adTableId = tableId;
		}
		
		hql = "select cg from Emes_Code_Rule cg where cg.emesCodeRuleObject.table.id = '" + adTableId + "'";
		Query query = OBDal.getInstance().getSession().createQuery(hql);
		List<EmesCodeRule> list = query.list();
		return list;
	}
	
	private static String createCode(EmesCodeRule codeRule) {
		String hql = "select c from Emes_Code_Rule_Combination c where c.emesCodeRule.id = '" + codeRule.getId() + "' order by sequence";
		List<EmesCodeRuleCombination> list = OBDal.getInstance().getSession().createQuery(hql).list();
		if (list == null || list.size() == 0) {
			return null;
		}
		StringBuilder code = new StringBuilder();
		String str = null;
		String saveDateMax = null;
		if (codeRule.isSaveDateMax()) {
			// 判断是否存在日期列
			for (EmesCodeRuleCombination rule : list) {
				if ("YYYYMM".equals(rule.getCodeType()) || "YYMM".equals(rule.getCodeType())) {
					saveDateMax = yyyyMM.format(new Date());
					break;
				} else if ("YYYYMMDD".equals(rule.getCodeType()) || "YYMMDD".equals(rule.getCodeType())) {
					saveDateMax = yyyyMMdd.format(new Date());
					break;
				}
			}
		}
		for (EmesCodeRuleCombination rule : list) {
			if ("ORG".equals(rule.getCodeType())) {
				str = getOrgCode();
			} else if ("XL".equals(rule.getCodeType())) {
				String orgId = getOrgId();
				if (codeRule.isSaveOrgMax() == null || codeRule.isSaveOrgMax() == false) {
					orgId = null;
				}
				
				str = getSnCode(rule, saveDateMax, orgId);
			} else if ("SELF".equals(rule.getCodeType())) {
				str = getSelfCode(rule.getSql());
			} else if ("YYYYMM".equals(rule.getCodeType()) || "YYMM".equals(rule.getCodeType())) {
				str = yyyyMM.format(new Date());
			} else if ("YYYYMMDD".equals(rule.getCodeType()) || "YYMMDD".equals(rule.getCodeType())) {
				str = yyyyMMdd.format(new Date());
			} else {
				str = rule.getCodeValue();
			}
			code.append(str);
		}
		return code.toString();
	}
	
	private static String getOrgCode() {
		String userId = SessionInfo.getUserId();
		User user = OBDal.getInstance().get(User.class, userId);
		return user.getOrganization().getSearchKey();
	}
	
	private static String getOrgId() {
		String userId = SessionInfo.getUserId();
		User user = OBDal.getInstance().get(User.class, userId);
		return user.getOrganization().getId();
	}
	
	private static String getSelfCode(String sql) {
		String userId = SessionInfo.getUserId();
		sql = sql.replace("@AD_User_Id@", "?");
		sql = sql.replace("@AD_User_ID@", "?");
		sql = sql.replace("@Ad_User_Id@", "?");
		sql = sql.replace("@AD_USER_ID@", "?");
		sql = sql.replace("@ad_user_id@", "?");
		sql = sql.replace("@value@", "?");
		Query query = OBDal.getInstance().getSession().createSQLQuery(sql);
		query.setString(0, userId);
		return (String)query.uniqueResult();
	}
	
	private static String getSnCode(EmesCodeRuleCombination rule, String dateValue, String orgId) {
		if (orgId == null) {
			orgId = "0";
		}
		String sql = "select s.COUNTER_VALUE,s.Emes_SNCOUNTER_ID from Emes_SNCounter s " +
				"where s.Emes_CODE_RULE_ID = '" + rule.getEmesCodeRule().getId() + "' " +
				"  and s.ad_org_id = '" + orgId + "'";
		if (dateValue != null) {
			sql += " and s.COUNTER_DATE = '" + dateValue + "'";
		} else {
			sql += " and (s.COUNTER_DATE is null OR s.COUNTER_DATE = '')";
		}
		Object[] sn = (Object[]) OBDal.getInstance().getSession().createSQLQuery(sql).uniqueResult();
		long value = 1;
		if (sn == null) {
			String uuid = StringUtil.getUUID();
			String insert = "insert into Emes_SNCounter (Emes_SNCOUNTER_ID, COUNTER_NAME, COUNTER_VALUE, Emes_CODE_RULE_ID";
			if (orgId != null) {
				insert += ", ad_org_id";
			}
			insert += ", COUNTER_DATE) values ('" + uuid + "', '" + rule.getEmesCodeRule().getName() + "计数器', 2, '" + 
				rule.getEmesCodeRule().getId() + "', ";
			if (orgId != null) {
				insert += "'" + orgId + "', ";
			}
			if (dateValue != null) {
				insert += "'" + dateValue + "')";
			} else {
				insert += "'')";
			}
			SessionHandler.getInstance().getSession().createSQLQuery(insert).executeUpdate();
		} else {
			value = Long.parseLong(sn[0] + "");
			if (rule.getEmesCodeRule().isReset() != null && rule.getEmesCodeRule().isReset() && ((value + 1) + "").length() > rule.getCodeLength()) {
				value = 0;
			}
			
			String update = "update Emes_SNCounter set COUNTER_VALUE = " + (value + 1) + " where Emes_SNCOUNTER_ID = '" + sn[1] + "'";
			SessionHandler.getInstance().getSession().createSQLQuery(update).executeUpdate();
		}
		int length = (value + "").length();
		StringBuilder code = new StringBuilder();
		for (int i = length; i < rule.getCodeLength(); i++) {
			code.append("0");
		}
		code.append(value);
		return code.toString();
	}
}
